package hotel.board;

import hotel.board.circuit.ICase;
import hotel.board.circuit.ICircuit;
import hotel.dice.BuildDiceFaces;
import hotel.exception.BuildingsMissingException;
import hotel.exception.NotEnoughMoneyException;
import hotel.exception.NotEnoughPlaceException;
import hotel.exception.NotYourPropertyException;
import hotel.exception.UnbuyablePropertyException;
import hotel.exception.WaitingOperationException;
import hotel.hotel.IHotelsArea;
import hotel.hotel.IProperty;
import hotel.player.IPlayer;
import hotel.util.IObservableModel;

public interface IBoard extends IObservableModel {
	
	// REQUETES
	
	/**
	 * @return l'ensemble des joueurs de cette partie.
	 */
	IPlayer[] getPlayers();
	
	/**
	 * @return le joueur dont c'est le tour de jouer.
	 */
	IPlayer getCurrentPlayer();
	
	/**
	 * @return le circuit de ce plateau.
	 */
	ICircuit getCircuit();
	
	/**
	 * @return la zone des hôtels de ce plateau.
	 */
	IHotelsArea getHotelsArea();
	
	/**
	 * @return le dé de mouvement.
	 */
	Integer getMoveDiceFace();
	
	/**
	 * @return le dé de construction.
	 */
	BuildDiceFaces getBuildDiceFace();

	/**
	 * @param p la propriété à interroger.
	 * @return le propriétaire de la propriété p, null sinon.
	 */
	IPlayer getOwner(IProperty p);
	
	// COMMANDES
	
	/**
	 * @return la valeur sur le sommet du dé une fois lancé.
	 */
	Integer rollMoveDice();
	
	/**
	 * @return la valeur sur le sommet du dé une fois lancé.
	 */
	BuildDiceFaces rollBuildDice();
	
	/**
	 * Fait avancer le joueur courant de la quantité de cases indiquée sur le dé de mouvement.
	 */
	void walkPlayer();
	
	/**
	 * @param c la case sur laquelle ajouter une entrée
	 * @param side le côté sur lequel ajouter une entrée
	 * @throws NotEnoughPlaceException une entrée existe déjà sur cette case.
	 * @throws BuildingsMissingException il n'y a pas de bâtiment de ce côté.
	 * @throws NotYourPropertyException la propriété adjascente n'appartient pas au joueur courant.
	 * @throws NotEnoughMoneyException le joueur courant n'a pas assez d'argent.
	 */
	void buildEntry(ICase c, int side) throws NotEnoughPlaceException, BuildingsMissingException, NotYourPropertyException, NotEnoughMoneyException;
	
	/**
	 * @param p la propriété sur laquelle poser un bâtiment supplémentaire.
	 * @throws NotEnoughMoneyException le joueur n'a pas assez d'argent pour construire un tel bâtiment.
	 * @throws NotYourPropertyException la propriété n'appartient pas au joueur courant.
	 * @throws NotEnoughPlaceException il n'y a pas de place pour un bâtiment supplémentaire.
	 */
	void build(IProperty p) throws NotEnoughMoneyException, NotYourPropertyException, NotEnoughPlaceException;
	
	/**
	 * @param p la propriété sur laquelle ajouter une base de loisirs.
	 * @throws NotEnoughMoneyException le joueur n'a pas assez d'argent pour construire cette base.
	 * @throws NotYourPropertyException la propriété n'appartient pas au joueur courant.
	 * @throws BuildingsMissingException tous les bâtiments n'ont pas été construits sur cette propriété.
	 * @throws NotEnoughPlaceException une base a déjà été construite sur cette propriété.
	 */
	void addFunArea(IProperty p) throws NotEnoughMoneyException, NotYourPropertyException, BuildingsMissingException, NotEnoughPlaceException;
	
	/**
	 * @param p la propriété à acheter
	 * @throws NotEnoughMoneyException le joueur n'a pas assez d'argent pour acheter cette propriété.
	 * @throws UnbuyablePropertyException la propriété ne peut être achetée.
	 */
	void buy(IProperty p) throws NotEnoughMoneyException, UnbuyablePropertyException;
	
	/**
	 * @param p la propriété à vendre
	 * @param cost le prix auquel vendre la propriété
	 * @param to le joueur à qui vendre la propriété
	 * @throws NotYourPropertyException la propriété n'appartient pas au joueur courant.
	 * @throws NotEnoughMoneyException le joueur à qui vendre n'a pas assez d'argent.
	 */
	void sellProperty(IProperty p, long cost, IPlayer to) throws NotYourPropertyException, NotEnoughMoneyException;
	
	/**
	 * @throws WaitingOperationException le jeu n'est pas dans un état de fin de tour.
	 */
	void endTurn() throws WaitingOperationException;

}
